package com.shire.shire_interface.controller.kf;

import com.shire.shire_interface.common.exception.ServiceException;
import com.shire.shire_interface.common.utils.JsonFormat;
import com.shire.shire_interface.common.utils.StrUtils;
import com.shire.shire_interface.service.kf.WebScoketService;
import com.shire.shire_interface.service.user.SystemUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArraySet;

@ServerEndpoint(value = "/ws/server")
@Component
public class WebSocketController {

    @Resource
    private SystemUserService systemUserService;

    private static Logger logger = LoggerFactory.getLogger(WebSocketController.class);

    private static volatile int onlineCount = 0;

    //concurrent包的线程安全Set，用来存放每个客户端对应的MyWebSocket对象。
    private static CopyOnWriteArraySet<WebSocketController> webSocketSet = new CopyOnWriteArraySet<>();

    //与某个客户端的连接会话，需要通过它来给客户端发送数据
    private Session session;


    //接收sid
    private String sid = "";

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, EndpointConfig config) {
        try {

            String queryString = session.getQueryString();
            String[] split = queryString.split("=");
            Integer userId = Integer.parseInt(split[1]);
//            SystemUser systemUser = systemUserService.getUserByUserId(2);

            logger.info("登录用户：" + userId);
            this.sid = "" + userId;
            clearOtherSession(this.sid);
            this.session = session;
            webSocketSet.add(this);
            addOnlineCount();
            logger.info("有新窗口开始监听 csId:" + sid + ",当前在线人数为" + getOnlineCount());
            sendMessage("{\"msg\":\"连接成功\"}");
        } catch (IOException e) {
            logger.error("websocket IO异常", e);
        }
    }

    private static void clearOtherSession(String sid) {
        for (WebSocketController webSocketController : webSocketSet) {
            if (StrUtils.getNullStr(sid).equalsIgnoreCase(webSocketController.getSid())) {
                try {
                    webSocketController.sendMessage("{\"msg\":\"您的账号再其它地方登录，账号被踢出！！！\", \"opType\":403}");
                    webSocketController.getSession().close(new CloseReason(CloseReason.CloseCodes.CANNOT_ACCEPT, "用户ID非法"));
                    return;
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        logger.debug("收到来自客服[" + sid + "]的信息:" + message);
        if (!StrUtils.getNullStr(message).startsWith("{")) {
            return;
        }
        WebScoketService.getInstance().receiveMessage(sid, message);
    }

    @OnError
    public void onError(Session session, Throwable error) {
        logger.error("发生错误sid={}", sid);
        error.printStackTrace();
    }

    /**
     * 实现服务器主动推送
     */
    public void sendMessage(String message) throws IOException {
        synchronized (this.session) {
            this.session.getBasicRemote().sendText(message);
        }
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        webSocketSet.remove(this);  //从set中删除
        subOnlineCount();           //在线数减1
        logger.info("有一连接关闭！当前在线人数为" + getOnlineCount());
    }

    public String getSid() {
        return sid;
    }

    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        WebSocketController.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        WebSocketController.onlineCount--;
    }

    public Session getSession() {
        return session;
    }

    public static void sendMessage(String sid, Map<String, Object> map) throws ServiceException {
        sendMessage(sid, JsonFormat.toJson(map));
    }

    public static void sendMessage(String sid, String message) throws ServiceException {
        WebSocketController webSocketServer = null;
        for (WebSocketController ws : webSocketSet) {
            if (ws.getSid().equalsIgnoreCase(sid)) {
                webSocketServer = ws;
                break;
            }
        }
        if (webSocketServer == null) {
//            logger.error("客服未在线！！sid={}", sid);
        } else {
            try {
                webSocketServer.sendMessage(message);
            } catch (IOException e) {
//                logger.error("发送消息失败,sid=" + sid + ", message=" + message + "", e);
            }
        }
    }
}
